import logging
import random
import numpy as np

from collections import defaultdict

from util.util_log import setup_logging
from util.util_csv import save_csv
from util.util_image import save_img, save_img_xyz, save_line_chart
from util.util_ris_pattern import point_2_phi_pattern, phase_2_bit, phase_2_pattern, phase_2_pattern_xyz_fft, \
    phase_2_pattern_xyz, eps, nRow

from multi_beam.multi_beam_PS import psm_beam_2, psm_beam_4, psm_beam_n

from util.util_analysis_plane import get_peaks, get_peak_3rd, get_peak_5th, get_peak_9th


# 配置日志，默认打印到控制台，也可以设置打印到文件
setup_logging()
# setup_logging(log_file="../../files/logs/log_multi_beam_PS.log")
# 获取日志记录器并记录日志
logger = logging.getLogger("[RIS-multi-beam-PS-1bit]")


# ============================================= 哈里斯鹰优化算法 ===========================================
class RISHarrisHawksOptimization:
    __bit_num = 0  # 比特数
    __beam_num = 0  # 波束数

    def __init__(self, bit_num, beam_num, num_hawks=50, max_iter=100, lb=-180, ub=180, phase_mix_init=None):
        self.__bit_num = bit_num
        self.__beam_num = beam_num
        self.num_hawks = num_hawks  # 鹰的数量
        self.max_iter = max_iter  # 最大迭代次数
        if phase_mix_init is not None:
            self.lb = np.full(phase_mix_init.shape, lb)  # 搜索空间下界
            self.ub = np.full(phase_mix_init.shape, ub)  # 搜索空间上界
        else:
            self.lb = np.full((nRow, nRow), lb)  # 搜索空间下界
            self.ub = np.full((nRow, nRow), ub)  # 搜索空间上界
        self.hawks = None  # 鹰的位置
        self.best_fitness = float('inf')  # 最佳适应度
        self.best_position = None  # 最佳位置
        self.iteration = 0  # 当前迭代次数
        self.best_fitness_history = []      # 保存每一代的最佳适应度值
        self.best_individual_history = []   # 保存每一代的最佳适应度个体

    def __get_psll_2(self, patternBit_mix):
        psll = 0
        # pattern 转dB
        pattern_dbw = 20 * np.log10(np.abs(patternBit_mix) / np.max(np.max(np.abs(patternBit_mix))) + eps)
        # pattern找峰值
        peaks = get_peaks(pattern_dbw)
        # 找第三峰(小于3dB)作为 PSLL
        if len(peaks) > 2:
            peak_3rd = get_peak_3rd(peaks)
            if peak_3rd is not None:
                psll = peak_3rd[0]
        return psll

    def __get_psll_4(self, patternBit_mix):
        psll = 0
        # pattern 转dB
        pattern_dbw = 20 * np.log10(np.abs(patternBit_mix) / np.max(np.max(np.abs(patternBit_mix))) + eps)
        # pattern找峰值
        peaks = get_peaks(pattern_dbw)
        # 找第三峰(小于3dB)作为 PSLL
        if len(peaks) > 4:
            peak_5th = get_peak_5th(peaks)
            if peak_5th is not None:
                psll = peak_5th[0]
        return psll

    def __get_psll_8(self, patternBit_mix):
        psll = 0
        # pattern 转dB
        pattern_dbw = 20 * np.log10(np.abs(patternBit_mix) / np.max(np.max(np.abs(patternBit_mix))) + eps)
        # pattern找峰值
        peaks = get_peaks(pattern_dbw)
        # 找第三峰(小于3dB)作为 PSLL
        if len(peaks) > 8:
            peak_9th = get_peak_9th(peaks)
            if peak_9th is not None:
                psll = peak_9th[0]
        return psll

    def __get_psll(self, patternBit_mix):
        psll = 0
        if self.__beam_num == 2:
            psll = self.__get_psll_2(patternBit_mix)
        elif self.__beam_num == 4:
            psll = self.__get_psll_4(patternBit_mix)
        elif self.__beam_num == 8:
            psll = self.__get_psll_8(patternBit_mix)
        return psll

    def fitness(self, phase_mix):
        # 相位转换 X bit
        phaseBit_mix, phaseBitDeg_mix = phase_2_bit(phase_mix, self.__bit_num)
        # 计算phase_mix的方向图
        phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
        # patternBit_mix = phase_2_pattern(phaseBit_mix)                # 公式法直接计算, 准确但速度太慢
        patternBit_mix, x, y = phase_2_pattern_xyz_fft(phaseBit_mix)  # FFT法计算, 快速
        # 计算码阵的最大副瓣
        psll = self.__get_psll(patternBit_mix)
        return psll

    # def fitness(self, cluster_init):
    #     list_sum = []
    #     for datas in cluster_init:
    #         sum = 0
    #         for data in datas:
    #             sum += data
    #         list_sum.append(sum)
    #     fit = 0
    #     for sum in list_sum:
    #         fit += sum ** 2
    #     return -fit

    def initialize_population(self, phase_mix_init):
        # 初始化鹰的位置
        self.hawks = np.random.uniform(self.lb, self.ub, (self.num_hawks, *phase_mix_init.shape))
        # 将初始位置设置为第一个鹰的位置
        self.hawks[0] = phase_mix_init
        # 确保初始位置在边界内
        self.hawks[0] = np.clip(self.hawks[0], self.lb, self.ub)
        # 计算初始适应度
        fitness_values = [self.fitness(hawk) for hawk in self.hawks]
        best_index = np.argmin(fitness_values)
        self.best_fitness = fitness_values[best_index]
        self.best_position = self.hawks[best_index].copy()

    def update_position(self):
        # 更新位置
        for i in range(self.num_hawks):
            E0 = 2 * (1 - (self.iteration / self.max_iter))
            E = 2 * E0 * np.random.rand() - E0
            J = 2 * (1 - np.random.rand())

            if abs(E) >= 1:
                # 软包围
                X_rand = self.hawks[np.random.randint(0, self.num_hawks)]
                D_X_rand = abs(J * X_rand - self.hawks[i])
                self.hawks[i] = X_rand - D_X_rand
            else:
                # 硬包围
                S = self.best_position - self.hawks[i]
                if np.random.rand() < 0.5:
                    # 攻击模式1
                    D_S = abs(S)
                    L = np.random.uniform(-1, 1, size=self.best_position.shape)
                    self.hawks[i] = self.best_position - E * D_S * L
                else:
                    # 攻击模式2
                    Y = self.hawks[np.random.randint(0, self.num_hawks)]
                    Z = self.hawks[np.random.randint(0, self.num_hawks)]
                    Y_new = Y - (np.random.rand() * abs(Y - Z))
                    S_Y = self.best_position - Y_new
                    self.hawks[i] = Y_new - E * abs(S_Y)

            # 应用边界条件
            self.hawks[i] = np.clip(self.hawks[i], self.lb, self.ub)

    def run(self, phase_mix_init):
        logger.info("num_hawks=%d, max_iter=%d" % (self.num_hawks, self.max_iter))

        # 如果在初始化时没有提供 phase_mix_init，则在这里重新初始化
        if self.lb is None or self.ub is None:
            self.lb = np.full(phase_mix_init.shape, -180)  # 搜索空间下界
            self.ub = np.full(phase_mix_init.shape, 180)  # 搜索空间上界

        # 初始化返回值
        self.initialize_population(phase_mix_init)

        for self.iteration in range(self.max_iter):
            self.update_position()
            # 计算当前适应度
            fitness_values = [self.fitness(hawk) for hawk in self.hawks]
            best_index = np.argmin(fitness_values)
            current_best_fitness = fitness_values[best_index]

            if current_best_fitness < self.best_fitness:
                self.best_fitness = current_best_fitness
                self.best_position = self.hawks[best_index].copy()

            # 记录最佳适应度曲线
            self.best_fitness_history.append(self.best_fitness)
            self.best_individual_history.append(self.best_position.copy())

            logger.info("iteration=%d: self.best_fitness=%f" % (self.iteration, self.best_fitness))

        # 返回最佳个体、最佳适应度、历史最佳适应度和历史最佳个体
        return self.best_position, self.best_fitness, self.best_fitness_history, self.best_individual_history


# ============================================= 主函数 ====================================
# HHO-PS 核心算法 -- 双波束
def hho_ps_beam_2(phase1, phase2, bit_num):
    # 1.PS方式初始化结果
    phase_mix, phaseBit_mix, phaseBitDeg_mix = psm_beam_2(phase1, phase2, bit_num)
    # 2.哈里斯鹰优化算法(HHO)寻找最优的phaseBit_mix
    hho = RISHarrisHawksOptimization(bit_num, 2, 50, 150, -180, 180)
    best_individual, best_fitness, best_fitness_history, best_individual_history = hho.run(phase_mix)
    # logger.info("best_individual:%s" % (best_individual))
    logger.info("Best Fitness=%f" % (best_fitness))
    #
    return best_individual, best_fitness, best_fitness_history, best_individual_history


# HHO-PS 核心算法 -- 四波束
def hho_ps_beam_4(phase1, phase2, phase3, phase4, bit_num):
    # 1.PS方式初始化结果
    phase_mix, phaseBit_mix, phaseBitDeg_mix = psm_beam_4(phase1, phase2, phase3, phase4, bit_num)
    # 2.哈里斯鹰优化算法(HHO)寻找最优的phaseBit_mix
    hho = RISHarrisHawksOptimization(bit_num, 4, 50, 150, -180, 180)
    best_individual, best_fitness, best_fitness_history, best_individual_history = hho.run(phase_mix)
    # logger.info("best_individual:%s" % (best_individual))
    logger.info("Best Fitness=%f" % (best_fitness))
    #
    return best_individual, best_fitness, best_fitness_history, best_individual_history


# HHO-PS 核心算法 -- 八波束
def hho_ps_beam_8(phase1, phase2, phase3, phase4, phase5, phase6, phase7, phase8, bit_num):
    # 1.PS方式初始化结果
    phase_mix, phaseBit_mix, phaseBitDeg_mix = psm_beam_n(
        [phase1, phase2, phase3, phase4, phase5, phase6, phase7, phase8], bit_num)
    # 2.哈里斯鹰优化算法(HHO)寻找最优的phaseBit_mix
    hho = RISHarrisHawksOptimization(bit_num, 8, 50, 150, -180, 180)
    best_individual, best_fitness, best_fitness_history, best_individual_history = hho.run(phase_mix)
    # logger.info("best_individual:%s" % (best_individual))
    logger.info("Best Fitness=%f" % (best_fitness))
    #
    return best_individual, best_fitness, best_fitness_history, best_individual_history


# 几何分区法 -- 双波束
def main_multi_beam_2(theta1, phi1, theta2, phi2, path_pre, bit_num):
    logger.info("main_multi_beam_2: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("main_multi_beam_2: theta1=%d, phi1=%d, theta2=%d, phi2=%d, " % (theta1, phi1, theta2, phi2))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_2: bit_num bigger than 2.")
        return
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    # 确保 phase1 和 phase2 具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape, "phase1 和 phase2 必须具有相同的形状"
    # HHO-PS
    phase_mix, best_fitness, best_fitness_history, best_individual_history = hho_ps_beam_2(phase1, phase2, bit_num)
    # 相位转换 X bit
    phaseBit_mix, phaseBitDeg_mix = phase_2_bit(phase_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    #
    # 保存结果
    logger.info("save HHO-PS multi-beam 2 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    save_img(path_pre + "phase1.jpg", phase1)
    save_img(path_pre + "phase2.jpg", phase2)
    save_img(path_pre + "phaseBit1.jpg", phaseBit1)
    save_img(path_pre + "phaseBit2.jpg", phaseBit2)
    save_img(path_pre + "pattern1.jpg", pattern1)
    save_img(path_pre + "pattern2.jpg", pattern2)
    save_img(path_pre + "phaseBit_mix.jpg", phaseBit_mix)         # 几何分区法 -- 结果码阵
    save_img(path_pre + "patternBit_mix.jpg", patternBit_mix)     # 几何分区法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    # 保存相位结果
    save_csv(phase1, path_pre + "phase1.csv")
    save_csv(phase2, path_pre + "phase2.csv")
    save_csv(phaseBit1, path_pre + "phaseBit1.csv")
    save_csv(phaseBit2, path_pre + "phaseBit2.csv")
    save_csv(phaseBit_mix, path_pre + "phaseBit_mix.csv")
    # 保存哈里斯鹰优化算法优化结果
    save_line_chart(path_pre + "best_fitness_history.jpg", best_fitness_history,
                    "best_fitness_history", "iteration", "best_fitness", "fitness")
    save_csv([[item] for item in best_fitness_history], path_pre + "best_fitness_history.csv")
    save_csv(best_individual_history, path_pre + "best_individual_history.csv")


# 几何分区法 -- 四波束
def main_multi_beam_4(theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4, path_pre, bit_num):
    logger.info("main_multi_beam_4: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("main_multi_beam_4: theta1=%d, phi1=%d, theta2=%d, phi2=%d, theta3=%d, phi3=%d, theta4=%d, phi4=%d"
                % (theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_N: bit_num bigger than 2.")
        return
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    phase3, phaseBit3, pattern3 = point_2_phi_pattern(theta3, phi3, bit_num)
    phase4, phaseBit4, pattern4 = point_2_phi_pattern(theta4, phi4, bit_num)
    # 确保所有数组具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape == phaseBit3.shape == phaseBit4.shape, "所有数组必须具有相同的形状"
    # HHO-PS
    phase_mix, best_fitness, best_fitness_history, best_individual_history \
        = hho_ps_beam_4(phase1, phase2, phase3, phase4, bit_num)
    # 相位转换 X bit
    phaseBit_mix, phaseBitDeg_mix = phase_2_bit(phase_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    # 计算phase_mix
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    #
    # 保存结果
    logger.info("save HHO-PS multi-beam 4 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    save_img(path_pre + "phase1.jpg", phase1)
    save_img(path_pre + "phase2.jpg", phase2)
    save_img(path_pre + "phase3.jpg", phase3)
    save_img(path_pre + "phase4.jpg", phase4)
    save_img(path_pre + "phaseBit1.jpg", phaseBit1)
    save_img(path_pre + "phaseBit2.jpg", phaseBit2)
    save_img(path_pre + "phaseBit3.jpg", phaseBit3)
    save_img(path_pre + "phaseBit4.jpg", phaseBit4)
    save_img(path_pre + "pattern1.jpg", pattern1)
    save_img(path_pre + "pattern2.jpg", pattern2)
    save_img(path_pre + "pattern3.jpg", pattern3)
    save_img(path_pre + "pattern4.jpg", pattern4)
    save_img(path_pre + "phase_mix.jpg", phaseBit_mix)       # 几何分区法 -- 结果码阵
    save_img(path_pre + "pattern_mix.jpg", patternBit_mix)   # 几何分区法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    # 保存相位结果
    save_csv(phase1, path_pre + "phase1.csv")
    save_csv(phase2, path_pre + "phase2.csv")
    save_csv(phase3, path_pre + "phase3.csv")
    save_csv(phase4, path_pre + "phase4.csv")
    save_csv(phaseBit1, path_pre + "phaseBit1.csv")
    save_csv(phaseBit2, path_pre + "phaseBit2.csv")
    save_csv(phaseBit3, path_pre + "phaseBit3.csv")
    save_csv(phaseBit4, path_pre + "phaseBit4.csv")
    save_csv(phaseBit_mix, path_pre + "phase_mix.csv")
    # 保存哈里斯鹰优化算法优化结果
    save_line_chart(path_pre + "best_fitness_history.jpg", best_fitness_history,
                    "best_fitness_history", "iteration", "best_fitness", "fitness")
    save_csv([[item] for item in best_fitness_history], path_pre + "best_fitness_history.csv")
    save_csv(best_individual_history, path_pre + "best_individual_history.csv")


def main_multi_beam_8(theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4,
                      theta5, phi5, theta6, phi6, theta7, phi7, theta8, phi8,
                      path_pre, bit_num):
    logger.info("main_multi_beam_8: bit_num=%d, path_pre=%s, " % (bit_num, path_pre))
    logger.info("main_multi_beam_8: theta1=%d, phi1=%d, theta2=%d, phi2=%d, theta3=%d, phi3=%d, theta4=%d, phi4=%d, "
                "theta5=%d, phi5=%d, theta6=%d, phi6=%d, theta7=%d, phi7=%d, theta8=%d, phi8=%d"
                % (theta1, phi1, theta2, phi2, theta3, phi3, theta4, phi4,
                   theta5, phi5, theta6, phi6, theta7, phi7, theta8, phi8))
    # 目前只支持2bit
    if bit_num > 2:
        logger.error("main_multi_beam_8: bit_num bigger than 2.")
        return
    # 获取所有的 phaseBit 变量
    phase1, phaseBit1, pattern1 = point_2_phi_pattern(theta1, phi1, bit_num)
    phase2, phaseBit2, pattern2 = point_2_phi_pattern(theta2, phi2, bit_num)
    phase3, phaseBit3, pattern3 = point_2_phi_pattern(theta3, phi3, bit_num)
    phase4, phaseBit4, pattern4 = point_2_phi_pattern(theta4, phi4, bit_num)
    phase5, phaseBit5, pattern5 = point_2_phi_pattern(theta5, phi5, bit_num)
    phase6, phaseBit6, pattern6 = point_2_phi_pattern(theta6, phi6, bit_num)
    phase7, phaseBit7, pattern7 = point_2_phi_pattern(theta7, phi7, bit_num)
    phase8, phaseBit8, pattern8 = point_2_phi_pattern(theta8, phi8, bit_num)
    # 确保所有数组具有相同的形状
    assert phaseBit1.shape == phaseBit2.shape == phaseBit3.shape == phaseBit4.shape == \
           phaseBit5.shape == phaseBit6.shape == phaseBit7.shape == phaseBit8.shape, "所有数组必须具有相同的形状"
    # HHO-PS
    phase_mix, best_fitness, best_fitness_history, best_individual_history \
        = hho_ps_beam_8(phase1, phase2, phase3, phase4, phase5, phase6, phase7, phase8, bit_num)
    # 相位转换 X bit
    phaseBit_mix, phaseBitDeg_mix = phase_2_bit(phase_mix, bit_num)
    # 计算phase_mix的方向图
    phaseBit_mix = np.deg2rad(phaseBitDeg_mix)
    # 计算phase_mix
    patternBit_mix = phase_2_pattern(phaseBit_mix)
    # 保存结果
    logger.info("save HHO-PS multi-beam 8 result...")
    patternBit_mix_xyz, x, y, z = phase_2_pattern_xyz(phaseBit_mix)
    # 保存图片
    save_img(path_pre + "phase1.jpg", phase1)
    save_img(path_pre + "phase2.jpg", phase2)
    save_img(path_pre + "phase3.jpg", phase3)
    save_img(path_pre + "phase4.jpg", phase4)
    save_img(path_pre + "phase5.jpg", phase5)
    save_img(path_pre + "phase6.jpg", phase6)
    save_img(path_pre + "phase7.jpg", phase7)
    save_img(path_pre + "phase8.jpg", phase8)
    save_img(path_pre + "phaseBit1.jpg", phaseBit1)
    save_img(path_pre + "phaseBit2.jpg", phaseBit2)
    save_img(path_pre + "phaseBit3.jpg", phaseBit3)
    save_img(path_pre + "phaseBit4.jpg", phaseBit4)
    save_img(path_pre + "phaseBit5.jpg", phaseBit5)
    save_img(path_pre + "phaseBit6.jpg", phaseBit6)
    save_img(path_pre + "phaseBit7.jpg", phaseBit7)
    save_img(path_pre + "phaseBit8.jpg", phaseBit8)
    save_img(path_pre + "pattern1.jpg", pattern1)
    save_img(path_pre + "pattern2.jpg", pattern2)
    save_img(path_pre + "pattern3.jpg", pattern3)
    save_img(path_pre + "pattern4.jpg", pattern4)
    save_img(path_pre + "pattern5.jpg", pattern5)
    save_img(path_pre + "pattern6.jpg", pattern6)
    save_img(path_pre + "pattern7.jpg", pattern7)
    save_img(path_pre + "pattern8.jpg", pattern8)
    save_img(path_pre + "phaseBit_mix.jpg", phaseBit_mix)  # 几何分区法 -- 结果码阵
    save_img(path_pre + "patternBit_mix.jpg", patternBit_mix)  # 几何分区法 -- 结果码阵方向图
    save_img_xyz(path_pre + "patternBit_mix_xyz.jpg", np.abs(patternBit_mix_xyz), x, y)
    # 保存相位结果
    save_csv(phase1, path_pre + "phase1.csv")
    save_csv(phase2, path_pre + "phase2.csv")
    save_csv(phase3, path_pre + "phase3.csv")
    save_csv(phase4, path_pre + "phase4.csv")
    save_csv(phase5, path_pre + "phase5.csv")
    save_csv(phase6, path_pre + "phase6.csv")
    save_csv(phase7, path_pre + "phase7.csv")
    save_csv(phase8, path_pre + "phase8.csv")
    save_csv(phaseBit1, path_pre + "phaseBit1.csv")
    save_csv(phaseBit2, path_pre + "phaseBit2.csv")
    save_csv(phaseBit3, path_pre + "phaseBit3.csv")
    save_csv(phaseBit4, path_pre + "phaseBit4.csv")
    save_csv(phaseBit5, path_pre + "phaseBit5.csv")
    save_csv(phaseBit6, path_pre + "phaseBit6.csv")
    save_csv(phaseBit7, path_pre + "phaseBit7.csv")
    save_csv(phaseBit8, path_pre + "phaseBit8.csv")
    save_csv(phaseBit_mix, path_pre + "phaseBit_mix.csv")
    # 保存哈里斯鹰优化算法优化结果
    save_line_chart(path_pre + "best_fitness_history.jpg", best_fitness_history,
                    "best_fitness_history", "iteration", "best_fitness", "fitness")
    save_csv([[item] for item in best_fitness_history], path_pre + "best_fitness_history.csv")
    save_csv(best_individual_history, path_pre + "best_individual_history.csv")


# ======================================================= main 主方法 ===============================================
def main_multi_hho_ps():
    # 基于HHO-PS的方法: 主函数
    # 测试方法
    #
    # 几何分区法: 主函数
    # main_multi_beam_2(30, 0, 30, 90,
    #                   "../files/multi-beam/1bit/HHO-PS/2-(30,0,30,90)/", 1)
    # main_multi_beam_2(30, 0, 30, 180,
    #                   "../files/multi-beam/1bit/HHO-PS/2-(30,0,30,180)/", 1)
    # main_multi_beam_4(30, 0, 30, 60, 30, 120, 30, 180,
    #                   "../files/multi-beam/1bit/HHO-PS/4-(30,0,30,60,30,120,30,180)/", 1)
    # main_multi_beam_4(30, 0, 30, 90, 30, 180, 30, 270,
    #                   "../files/multi-beam/1bit/HHO-PS/4-(30,0,30,90,30,180,30,270)/", 1)
    # main_multi_beam_8(30, 0, 30, 45, 30, 90, 30, 135, 30, 180, 30, 225, 30, 270, 30, 315,
    #                   "../files/multi-beam/1bit/HHO-PS/8-(30,45step)/", 1)
    #
    main_multi_beam_2(30, 0, 30, 90,
                      "../files/multi-beam/2bit/HHO-PS/2-(30,0,30,90)/", 2)
    main_multi_beam_2(30, 0, 30, 180,
                      "../files/multi-beam/2bit/HHO-PS/2-(30,0,30,180)/", 2)
    main_multi_beam_4(30, 0, 30, 60, 30, 120, 30, 180,
                      "../files/multi-beam/2bit/HHO-PS/4-(30,0,30,60,30,120,30,180)/", 2)
    main_multi_beam_4(30, 0, 30, 90, 30, 180, 30, 270,
                      "../files/multi-beam/2bit/HHO-PS/4-(30,0,30,90,30,180,30,270)/", 2)
    main_multi_beam_8(30, 0, 30, 45, 30, 90, 30, 135, 30, 180, 30, 225, 30, 270, 30, 315,
                      "../files/multi-beam/2bit/HHO-PS/8-(30,45step)/", 2)





if __name__ == '__main__':
    logger.info("1bit-RIS-multi-beam-PS: HHO based on PS method")
    main_multi_hho_ps()